/*
 * Copyright 2011-2017 CPJIT Group.
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.rui.baidu.map;

import cn.hutool.http.HttpUtil;
import cn.rui.baidu.map.res.AddressToLocation;
import cn.rui.baidu.map.res.LocationToAddress;
import cn.rui.baidu.map.res.Search;
import cn.rui.controller.MainController;
import com.google.gson.Gson;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 地理编码器。
 *
 * @since 1.0.0
 * @author yonghuan
 */
public class Geocoder {

	private final static String OUTPUT_JSON = "json";
	private String ak;
	private String sk;


	public Geocoder(String ak, String sk) {
		this.ak = ak;
		this.sk = sk;
	}

	public Search search(AddressToLocation location, MainController.InputInfo inputInfo){
//		http://api.map.baidu.com/place/v2/search?query=ATM机&tag=银行&region=北京&output=json&ak=您的ak
		AddressToLocation.ResultBean result = location.getResult();
		AddressToLocation.ResultBean.LocationBean location1 = result.getLocation();
		String loc =  location1.getLat() + "," + location1.getLng();

		Map<String, String> params = new LinkedHashMap<String, String>();
		params.put("query", "男装");
//		params.put("region", "全国");
		params.put("location", loc);
		params.put("coordtype", "bd09ll");
		params.put("radius", "1000");
		params.put("page_size", "20");
		params.put("page_num", "0");

		params.put("output", OUTPUT_JSON);
		params.put("ak", ak);
		String baseUrl = "http://api.map.baidu.com/place/v2/search?";
		StringBuilder url = new StringBuilder(baseUrl)
				.append(toQueryString(params))
				.append("&sn=").append(generateSn(baseUrl,params));
		System.out.println("url = " + url);
		String s = HttpUtil.get(url.toString());
		return new Gson().fromJson(s, Search.class);
	}

	/**
	 * 地理编码。
	 */
	public AddressToLocation addressToLocation(String address) throws Bmap4jException {
		// http://api.map.baidu.com/geocoder/v2/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
		// //GET请求
		Map<String, String> params = new LinkedHashMap<String, String>();
		params.put("address", address);
		params.put("ret_coordtype", "bd09ll");
		params.put("output", OUTPUT_JSON);
		params.put("ak", ak);
		String baseUrl = "http://api.map.baidu.com/geocoder/v2/?";
		StringBuilder url = new StringBuilder(baseUrl)
				.append(toQueryString(params))
				.append("&sn=").append(generateSn(baseUrl,params));
		String s = HttpUtil.get(url.toString());
		return new Gson().fromJson(s, AddressToLocation.class);
	}

	/**
	 * 逆地理编码。
	 */
	public LocationToAddress locationToAddress(AddressToLocation location) throws Bmap4jException {
		// http://api.map.baidu.com/geocoder/v2/?callback=renderReverse&location=39.934,116.329&output=json&pois=1&ak=您的ak
		Map<String, String> params = new LinkedHashMap<String, String>();
		AddressToLocation.ResultBean result = location.getResult();
		AddressToLocation.ResultBean.LocationBean location1 = result.getLocation();

		String loc =  location1.getLat() + "," + location1.getLng();
		params.put("location", loc);
		params.put("coordtype", "bd09ll");
		params.put("ret_coordtype", "bd09ll");
		params.put("extensions_poi", "null");
		params.put("output", OUTPUT_JSON);
		params.put("ak", ak);
		String baseUrl = "http://api.map.baidu.com/geocoder/v2/?";
		StringBuilder url = new StringBuilder(baseUrl)
				.append(toQueryString(params))
				.append("&sn=").append(generateSn(baseUrl,params));
		String s = HttpUtil.get(url.toString());
		return new Gson().fromJson(s, LocationToAddress.class);
	}

	private String generateSn(String baseUrl,Map<String, String> params){
		// 调用下面的toQueryString方法，对LinkedHashMap内所有value作utf8编码，拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
		String paramsStr = toQueryString(params);
		// 对paramsStr前面拼接上/geocoder/v2/?，后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
//		String wholeStr = new String("/geocoder/v2/?" + paramsStr + sk);
		String replace = baseUrl.replace("http://api.map.baidu.com", "");

		String wholeStr = new String( replace + paramsStr + sk);
		// 对上面wholeStr再作utf8编码
		String tempStr = null;
		try {
			tempStr = URLEncoder.encode(wholeStr, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		// 调用下面的MD5方法得到最后的sn签名7de5a22212ffaa9e326444c75a58f9a0
		return MD5(tempStr);
	}

	// 对Map内所有value作utf8编码，拼接返回结果
	private  String toQueryString(Map<?, ?> data) {
		StringBuffer queryString = new StringBuffer();
		for (Map.Entry<?, ?> pair : data.entrySet()) {
			queryString.append(pair.getKey() + "=");
			try {
				queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8") + "&");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		if (queryString.length() > 0) {
			queryString.deleteCharAt(queryString.length() - 1);
		}
		return queryString.toString();
	}

	// 来自stackoverflow的MD5计算方法，调用了MessageDigest库函数，并把byte数组结果转换成16进制
	private String MD5(String md5) {
		try {
			java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
			byte[] array = md.digest(md5.getBytes());
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < array.length; ++i) {
				sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
			}
			return sb.toString();
		} catch (java.security.NoSuchAlgorithmException e) {
		}
		return null;
	}

}
